package com.study.springbootsecurity.handler.sms;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.study.springbootsecurity.config.properties.JwtConfigProperties;
import com.study.springbootsecurity.entity.LoginUser;
import com.study.springbootsecurity.entity.business.RefreshResponse;
import com.study.springbootsecurity.service.impl.TokenService;
import com.study.springbootsecurity.util.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseCookie;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @Description: TODO 验证码登录成功处理器
 * @author: Huangjianyun
 * @date: 2025-06-14 21:01
 */
@Component
public class SmsCodeAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private final JwtConfigProperties jwtConfigProperties;
    private final TokenService tokenService;
    private final RedisCache redisCache;

    @Autowired
    public SmsCodeAuthenticationSuccessHandler(JwtConfigProperties jwtConfigProperties, TokenService tokenService, RedisCache redisCache) {
        this.jwtConfigProperties = jwtConfigProperties;
        this.tokenService = tokenService;
        this.redisCache = redisCache;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        // 单独处理 生成刷新令牌和访问令牌
        logger.info("登录成功");
        //登录成功 生成访问令牌和令牌存储并存储刷新令牌到redis
        //SecurityContextHolder.getContext().setAuthentication(authResult);
        LoginUser principal = (LoginUser)authentication.getPrincipal();
        // 生成refreshToken的key 并客户端标识绑定
        String deviceFinerPrint = DeviceFinerUtil.buildDeviceFingerprint(request);
        String accessToken = TokenUtil.createToken(principal.getSysUser(), jwtConfigProperties);
        String refreshToken = TokenUtil.createRefreshToken(principal.getUsername(),jwtConfigProperties,deviceFinerPrint);
        // 存储刷新令牌到redis
        String refreshTokenKey = "refresh"+":"+principal.getUsername()+":"+deviceFinerPrint;
        tokenService.saveRefreshToken(refreshTokenKey,refreshToken,jwtConfigProperties.getRefreshExpiration());
        // 存储系统用户类redis 有效期和refreshToken有效期一样 存储用户信息：用户名+":"+设备标识
        redisCache.set("user:info:"+principal.getUsername()+":"+deviceFinerPrint,principal.getSysUser(),jwtConfigProperties.getRefreshExpiration(), TimeUnit.SECONDS);
        // 设置刷新令牌到token
        ResponseCookie.from("refresh_token",refreshToken)
                .httpOnly(true)
                .secure(true)
                .path("/")
                .maxAge(jwtConfigProperties.getRefreshExpiration())// 设置 Cookie 有效期为 7 天（单位：秒）
                .sameSite("Strict")   // 严格限制跨站请求（防御 CSRF 攻击）
                .build();             // 构建 ResponseCookie 对象
        CookieUtil.set(response, "refresh_token", refreshToken,
                jwtConfigProperties.getRefreshExpiration(), // 秒
                "/", // 根路径
                true,
                true);
        // 登录成功 返回刷新令牌和访问令牌
        RefreshResponse refreshResponse = new RefreshResponse();
        refreshResponse.setRefreshToken(refreshToken);
        refreshResponse.setAccessToken(accessToken);
        Result<RefreshResponse> result = Result.success(refreshResponse);
        ResponseUtil.outJson(response,result);
    }
}